﻿
Imports System.Threading
Imports std

Public Module async_result_destructor
    Private ReadOnly ASYNC_OPERATION_FORCE_FINISH_TIMEMS As Int64
    Private ReadOnly are As AutoResetEvent = Nothing
    Private ReadOnly q As qless(Of void) = Nothing
    Private stopping As Boolean = False

    Sub New()
        ASYNC_OPERATION_FORCE_FINISH_TIMEMS =
            counter.registerAverageAndLastAverage("ASYNC_OPERATION_FORCE_FINISH_TIMEMS")
        are = New AutoResetEvent(False)
        q = New qless(Of void)()
        AddHandler applicationShutdown,
            Sub()
                stopping = True
            End Sub
        Dim ready_to_abort As singleentry
        ready_to_abort.mark_in_use()
        Dim th As Thread = Nothing
        th = startThread(Sub()
                             While Not q.empty() OrElse are.WaitOne()
                                 Dim v As void = Nothing
                                 If q.pop(v) Then
                                     assert(Not v Is Nothing)
                                     Dim n As Int64 = 0
                                     n = Now.milliseconds()
                                     Try
                                         ready_to_abort.mark_not_in_use()
                                         v()
                                     Catch ex As ThreadAbortException
                                         If Not stopping Then
                                             Thread.ResetAbort()
                                         End If
                                     Finally
                                         counter.increase(ASYNC_OPERATION_FORCE_FINISH_TIMEMS,
                                                          Now.milliseconds() - n)
                                     End Try
                                 End If
                             End While
                         End Sub)
        th.IsBackground() = True
        th.Name() = "ASYNC_RESULT_DESTRUCTOR_THREAD"
        queueInBackendThread(Of _16)(Sub()
                                         If ready_to_abort.mark_in_use() Then
                                             th.Abort()
                                         End If
                                     End Sub)
    End Sub

    Public Sub queue(ByVal state As async_state_t, ByVal ar As IAsyncResult)
        assert(Not state Is Nothing AndAlso Not ar Is Nothing)
        q.push(Sub()
                   state.mark_finish(ar, False)
               End Sub)
        are.Set()
    End Sub
End Module
